package sg.edu.nus.iss.jass.datastore.util;

import java.io.Serializable;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import sg.edu.nus.iss.jass.datastore.BaseDTO;


public class DataStoreHelper {
	
	
	
	/**
	 * find index by id
	 * @param <T>
	 * @param list
	 * @param id
	 * @return index of the id in given list
	 */
	public static <T extends BaseDTO> int getIndex(List<T> list, String id) {

		if (list == null) {
			return -1;
		}
		for (int i = 0; i < list.size(); i++) {
			if (list.get(i).getId().equals(id)) {
				return i;
			}
		}
		return -1;
	}

	/**
	 * Using binary seach to get the index of the passed in object in the list
	 * @param <T>
	 * @param list
	 * @param t
	 * @return int 
	 * 			index of object in list
	 */
	public static <T extends BaseDTO> int getIndex(List<T> list, T t) {

		if (list == null) {
			return -1;
		}
		Compare<T> c = new Compare<T>();
		Collections.sort(list, c);
		return Collections.binarySearch(list, t, c);
	}

	

	/**
	 * get the third level class name Object->BaseDTO->? if the class is not
	 * child of BaseDTO, return it's self class name
	 * 
	 * @param inClazz
	 * @return class name
	 */
	public static String getClazzName(final Class<?> inClazz) {
		return ((Class<?>)inClazz).getName();
		//return getSuperClassName(inClazz, BaseDTO.class);
	}

	/**
	 * return the objects of specified type and all the subclasses of the type
	 * 
	 * @param <T>
	 * @param list
	 * @param t
	 * @return List of Objects
	 */
	public static <T extends Serializable> List<T> filterByType(List<T> list, Type t) {

		if (list == null)
			return null;
		List<T> filterList = new ArrayList<T>();
		for (T obj : list) {
			// if obj is the subclass of type passed, return it
			if (((Class<?>) t).isAssignableFrom(obj.getClass())) {
				filterList.add(obj);
			}
		}
		if (filterList.isEmpty()) {
			return null;
		}
		return filterList;
	}
	
	/**
	 * get the child class name of stopClazz stopClazz->?<return> if the class is not
	 * child of stopClazz, return it's self class name
	 * 
	 * @param childClazz
	 * @return The class name
	 */
	private static String getSuperClassName(final Class<?> childClazz, final Class<?> stopClazz) {

		Class<?> clazz = childClazz;

		// if childClazz is not the subclass of stopClazz return the class name
		// directly
		if (!stopClazz.isAssignableFrom(clazz)) {
			return childClazz.getName();
		}
		while (true) {
			String className = clazz.getName();
			clazz = clazz.getSuperclass();
			if (clazz == stopClazz) {
				return className;
			}
			if (clazz == Object.class) {
				break;
			}
		}
		// this will not happen in our case
		return null;
	}
	
	/**
	 * implements comparator for order and search
	 * 
	 * @author Wang Dayong
	 * 
	 * @param <T> Child class of BaseDTO
	 */
	private static class Compare<T extends BaseDTO> implements Comparator<T> {

		@Override
		public int compare(T o1, T o2) {

			if (o1.equals(o2))
				return 0;
			else
				return o1.getId().compareTo(o2.getId());
		}

	}
}
